﻿using GCC.Container.Abstracts;

using MQManager = GCC.Container.MQ.Manager;

namespace GCC.APIContainer
{
    /// <summary>
    /// 容器上下文
    /// </summary>
    public partial class GCCContext : AbsGCCContext
    {
        /// <summary>
        /// 当前节点本地MQ地址
        /// </summary>
        private static string _localMQServer = "";
        /// <summary>
        /// 用户名
        /// </summary>
        private static string _localMQUserName = "";
        /// <summary>
        /// 密码
        /// </summary>
        private static string _localMQPassword = "";

        /// <summary>
        /// 获取MQ地址
        /// </summary>
        /// <returns></returns>
        private bool InitBaseInfo()
        {
            if (string.IsNullOrWhiteSpace(_localMQServer))
            {
                _localMQServer = GetConfigByPath(new string[] { _pointName ?? "", "LocalMQ", "Server" });
                _localMQUserName = GetConfigByPath(new string[] { _pointName ?? "", "LocalMQ", "UserName" });
                _localMQPassword = GetConfigByPath(new string[] { _pointName ?? "", "LocalMQ", "Password" });
                _logger?.Trace("Get Local mq Server address once.");
            }
            return !(string.IsNullOrWhiteSpace(_localMQServer)
                || string.IsNullOrWhiteSpace(_localMQUserName)
                || string.IsNullOrWhiteSpace(_localMQPassword));
        }

        /// <summary>
        /// 給本地的MQ服务发送一条消息
        /// </summary>
        /// <param name="queueName">目标队列名</param> 
        /// <param name="message">消息内容</param>  
        /// <param name="virtualHost">虚拟主机名,默认/</param>
        /// <param name="exchangeName">特定的交换机名称,不填默认amq.direct,请IT人员配置好</param>
        /// <param name="routingKey">特定的交换机路径名,不填默认就是MQ的名字.请IT人员配置好</param>  
        /// <returns>是否推送成功</returns>
        public override bool SendMessageToLocalMQ(string message,
            string queueName,
            string virtualHost = "/",
            string? exchangeName = null, string? routingKey = null)
        {
            if (InitBaseInfo())
            {
                _logger?.Critical($"Can not get the local MQ Info.");
                return false;
            }
            return MQManager.SendMessageTo(_localMQServer, _localMQUserName, _localMQPassword, virtualHost, queueName, message, exchangeName, routingKey);
        }

        /// <summary>
        /// 从本地的MQ中获取消息,连续性
        /// </summary>
        /// <param name="callBackMethod">回调函数,注意这是持续性的,考虑好释放时间,函数返回true则删除服务器消息,返回false则认为消费失败,重新回队列</param>       
        /// <param name="queueName">目标队列名</param> 
        /// <param name="virtualHost">虚拟主机名,默认/</param>
        /// <param name="canMutileThread">是否支持多线程,默认是true,如果填写false,那么将会进行串行回调</param>   
        /// <param name="exclusive">是否排他,也就是系统中不要出现第二个消费器</param>    
        public override string? GotMessageFromLocalMQ(Func<string, bool> callBackMethod,
            string queueName,
            string virtualHost = "/",
            bool canMutileThread = true,
            bool exclusive = false)
        {
            if (InitBaseInfo())
            {
                _logger?.Critical($"Can not get the local MQ Info.");
                return null;
            }
            return MQManager.GotMessageFrom(host: _localMQServer, userName: _localMQUserName, password: _localMQPassword, virtualHost: virtualHost, queueName: queueName, callBackMethod, canMutileThread: canMutileThread, exclusive: exclusive);
        }


        /// <summary>
        /// 从本地的MQ中获取消息,只触发一次
        /// </summary>        
        /// <param name="callBackMethod">回调函数,注意这是持续性的,考虑好释放时间,函数返回true则删除服务器消息,返回false则认为消费失败,重新回队列</param>      
        /// <param name="queueName">目标队列名</param> 
        /// <param name="virtualHost">虚拟主机名,默认/</param>       
        /// <param name="exclusive">是否排他,也就是系统中不要出现第二个消费器</param>     
        public override void GotOneMessageFromLocalMQ(Func<string, bool> callBackMethod,
            string queueName,
            string virtualHost = "/",
            bool exclusive = false)
        {
            if (InitBaseInfo())
            {
                _logger?.Critical($"Can not get the local MQ Info.");
                return;
            }
            MQManager.GotOneMessageFrom(host: _localMQServer, userName: _localMQUserName, password: _localMQPassword, virtualHost: virtualHost, queueName: queueName, callBackMethod, exclusive: exclusive);
        }

        /// <summary>
        /// 关闭一个通道, 跟GotMessageFromLocalMQ配合使用
        /// </summary>        
        /// <param name="token">token</param>      
        public override void CloseMQConnection(string token)
        {
            MQManager.CloseConnection(token);
        }


        /// <summary>
        /// 給本地的MQ服务发送一条消息
        /// </summary>
        /// <param name="host">主机地址,只支持:amqp</param>
        /// <param name="userName">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="queueName">目标队列名</param> 
        /// <param name="message">消息内容</param>  
        /// <param name="virtualHost">虚拟主机名,默认/</param>
        /// <param name="exchangeName">特定的交换机名称,不填默认amq.direct,请IT人员配置好</param>
        /// <param name="routingKey">特定的交换机路径名,不填默认就是MQ的名字.请IT人员配置好</param>  
        /// <returns>是否推送成功</returns>
        public override bool SendMessageToMQ(string host, string userName, string password, string message,
            string queueName,
            string virtualHost = "/",
            string? exchangeName = null,
            string? routingKey = null)
        {
            return MQManager.SendMessageTo(host, userName, password, virtualHost, queueName, message, exchangeName, routingKey);
        }

        /// <summary>
        /// 从本地的MQ中获取消息,连续性
        /// </summary>
        /// <param name="host">主机地址,只支持:amqp</param>
        /// <param name="userName">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="callBackMethod">回调函数,注意这是持续性的,考虑好释放时间,函数返回true则删除服务器消息,返回false则认为消费失败,重新回队列</param>       
        /// <param name="queueName">目标队列名</param> 
        /// <param name="virtualHost">虚拟主机名,默认/</param>
        /// <param name="canMutileThread">是否支持多线程,默认是true,如果填写false,那么将会进行串行回调</param>   
        /// <param name="exclusive">是否排他,也就是系统中不要出现第二个消费器</param>   
        /// <returns>channel的Token,用于关闭连接</returns>
        public override string? GotMessageFromMQ(string host, string userName, string password, Func<string, bool> callBackMethod,
            string queueName,
            string virtualHost = "/",
            bool canMutileThread = true,
            bool exclusive = false)
        {
            return MQManager.GotMessageFrom(host, userName, password, virtualHost: virtualHost, queueName: queueName, callBackMethod, canMutileThread: canMutileThread, exclusive: exclusive);

        }

        /// <summary>
        /// 从本地的MQ中获取消息,只触发一次
        /// </summary>        
        /// <param name="host">主机地址,只支持:amqp</param>
        /// <param name="userName">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="callBackMethod">回调函数,注意这是持续性的,考虑好释放时间,函数返回true则删除服务器消息,返回false则认为消费失败,重新回队列</param>      
        /// <param name="queueName">目标队列名</param> 
        /// <param name="virtualHost">虚拟主机名,默认/</param>       
        /// <param name="exclusive">是否排他,也就是系统中不要出现第二个消费器</param>    
        public override void GotOneMessageFromMQ(string host, string userName, string password, Func<string, bool> callBackMethod,
            string queueName,
            string virtualHost = "/",
            bool exclusive = false)
        {
            MQManager.GotOneMessageFrom(host, userName, password, virtualHost: virtualHost, queueName: queueName, callBackMethod, exclusive: exclusive);

        }
    }
}
